﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Data.Schema.Package.Project;
using Microsoft.Data.Schema.SchemaModel;
using System.ComponentModel;
using TFDP.Common.Configuration;
using TFDP.Common.T4;

namespace TFDP.Common
{
    /// <summary>
    /// This interface is used by classes that perform the generation operations and manage
    /// the workload that is supplied by the ProjectManager
    /// </summary>
    public interface IProcessor : INotifyPropertyChanged
    {
        /// <summary>
        /// The number of unique queued IModelElement instances
        /// </summary>
        int Count { get; }

        /// <summary>
        /// An IEnumerable&lt;Type&gt; that contains the types this processor supports
        /// </summary>
        IEnumerable<Type> SupportedTypes { get; }

        /// <summary>
        /// An IExtenderType instance that provides extra properties for the database file objects
        /// </summary>
        IExtenderType PropertyExtenderType { get; }

        /// <summary>
        /// The queue that contains the workitems
        /// </summary>
        ThreadsafeQueue<IModelElement> Queue { get; }

        /// <summary>
        /// true if the processor is started
        /// </summary>
        bool IsRunning { get; }

        /// <summary>
        /// true if the processor is stopped
        /// </summary>
        bool IsStopped { get; }

        /// <summary>
        /// true if the processor is currently processing queued elements
        /// </summary>
        bool IsBusy { get; }

        /// <summary>
        /// The name of the project as in the Solution Explorer
        /// </summary>
        string ProjectName { get; }

        /// <summary>
        /// The settings for this processor
        /// </summary>
        SettingsCollection Settings { get; }

        /// <summary>
        /// Initialize the processor
        /// </summary>
        /// <param name="project">The project that this processor is assigned to</param>
        void Initialize(IDatabaseProjectNode project, IServiceProvider serviceProvider);

        /// <summary>
        /// Enqueue an IModelElement for processing
        /// </summary>
        /// <param name="element">The element to process</param>
        void Enqueue(IModelElement element);

        /// <summary>
        /// Obtain the next GenerationItem instance from the output collection
        /// </summary>
        /// <returns>An instance of GenerationItem or null if no more instances are available</returns>
        GeneratedArtifact PopGenerationItem();

        /// <summary>
        /// Starts processing of queued elements
        /// </summary>
        void Start();

        /// <summary>
        /// Stops processing of queued elements
        /// </summary>
        void Stop();

        /// <summary>
        /// Starts the actual processing
        /// </summary>
        void DoWork();

        /// <summary>
        /// Returns the type name of the given element.
        /// For example: Table, Procedure, Trigger etc
        /// </summary>
        /// <param name="element">The element to get the typename for</param>
        /// <returns>The typename</returns>
        string GetTypeName(IModelElement element);

        /// <summary>
        /// Raised when the processor is starting
        /// </summary>
        event EventHandler<EventArgs> BeginProcessing;

        /// <summary>
        /// Raised when processing is completed and no more items remain in the queue
        /// </summary>
        event EventHandler<EventArgs> ProcessingComplete;

        /// <summary>
        /// Raised when all the items in the queue have been processed
        /// </summary>
        event EventHandler<EventArgs> GenerationCompleted;

        /// <summary>
        /// Raised when the queue is changed
        /// </summary>
        event EventHandler<EventArgs> QueueChanged;

        /// <summary>
        /// Raised when a IGenerator recompiles a template
        /// </summary>
        event EventHandler<TemplateRecompileEventArgs> TemplateRecompile;
    }
}
